package func;

import java.util.Arrays;
import java.util.Comparator;

import node.Node;
import ttt.*;

public class TicTacToeRankFunction implements RankFunction {
	
	private BoardEvaluator eval = 
		new BoardEvaluator();
	private Node[] pop;
	
	public void sortByRank(Node[] pop) {
		this.pop = pop;
		
		Comparator<Node> comp = new
			Comparator<Node>() {
				public int compare(Node n1, Node n2) {
					return applyScoreFunction(n1) - applyScoreFunction(n2);
				}
			};
		
		Arrays.sort(pop, comp);
	}

	/**
	 * @PRECONDITION sortByRank must be called first with a valid array. The node
	 * which is passed as the parameter in applyScoreFunction must be in the array.
	 * */
	public int applyScoreFunction(Node n) {
		if(pop == null)
			return 0;
		
		int loses = 0;
		for(Node node : pop) {
			if(node == n)
				continue;
			
			int winner = game(new Node[]{n, node});
			switch(winner) {
			case 0:
				loses = loses + 1;
				break;
			case -1:
				loses = loses + 2;
				break;
			}
		}
		
		for(Node node : pop) {
			if(node == n)
				continue;
			
			int winner = game(new Node[]{node, n});
			switch(winner) {
			case 0:
				loses = loses + 1;
				break;
			case 1:
				loses = loses + 2;
				break;
			}
		}
		
		return loses;
	}
	
	public int game(Node[] players) {
		int[] board = new int[9];
		int r = 0;
		while(eval.status(board) != BoardEvaluator.STATUS_UNDEFIND || r < 6) {
			int placeFirst = posRem(players[0].evaluate(board) % 9);
			if(!eval.isOccupied(board, placeFirst))
				board[placeFirst] = 1;
			
			if(eval.status(board) != BoardEvaluator.STATUS_UNDEFIND)
				break;
			
			int placeSecond = posRem(players[1].evaluate(board) % 9);
			if(!eval.isOccupied(board, placeSecond))
				board[placeSecond] = -1;
			
			r++;
		}
		
		if(eval.status(board) == BoardEvaluator.STATUS_UNDEFIND || eval.status(board) == BoardEvaluator.STATUS_TIE)
			return BoardEvaluator.STATUS_TIE;
		else
			return eval.status(board);
	}
	
	private int posRem(int k) {
		if(k < 0)
			return k + 9;
		else
			return k;
	}
}
